import auxiliares.Coordenada;
import auxiliares.HitTest;

import flash.display.DisplayObject;
import flash.display.Loader;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
import flash.media.Video;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.sampler.Sample;

import juego.Barco;
import juego.DoceMillas;
import juego.Proyectil;
import juego.Puerto;
import juego.Tierra;
import juego.Torpedo;

import mx.controls.Alert;
import mx.controls.MovieClipSWFLoader;
import mx.controls.SWFLoader;
import mx.core.UIComponent;
import mx.events.CloseEvent;
import mx.events.EffectEvent;
import mx.managers.CursorManager;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;


[Embed("img/cursor-ataque.png")]
private var cursorAtaque:Class;

[Embed("img/cursor-movimiento.png")]
private var cursorMovimiento:Class;

[Embed("img/cursor-virar.png")]
private var cursorVirar:Class;

[Embed("img/explosion.swf")]
private var explosion:Class;

[Embed("img/explosionAgua.swf")]
private var explosionAgua:Class;


/**
 * 
 * @param _event
 * 
 */
private function accionMouseJuego(_event:MouseEvent): void {
	if ( (_event.target.hasOwnProperty("id") && _event.target.id == "imgFondo") || !_event.target.hasOwnProperty("id")) {
		if (!barcos[seleccionado].isStopped()) {
			var xTo:Number = _event.stageX+pantalla.getXPantalla();
			var yTo:Number = _event.stageY+pantalla.getYPantalla();
			cnvBotonesSecundarios.visible = false;
			
			switch (accion) {
				case ACC_MOVER:
					if( _event.target.hasOwnProperty("name") && _event.target.name == "AreaVisiblidad_" + seleccionado  ){
						var destino: Coordenada = barcos[seleccionado].calcularDestino(xTo, yTo);
						ws.movimientoBarco(
							idPartida, jugadores[bando], seleccionado, destino.getX(), destino.getY(),
							barcos[seleccionado].calcularAngulo(xTo, yTo)
						);
					}
				break;
				case ACC_VIRAR:
					ws.virarBarco(
						idPartida, jugadores[bando], seleccionado,
						barcos[seleccionado].calcularAngulo(xTo, yTo)
					);
				break;
				case ACC_DISPARAR:
					if( _event.target.hasOwnProperty("name") && _event.target.name == "AreaDisparo_" + seleccionado && proyectiles[seleccionado + "_" + armaSeleccionada + "_0"] == null){
						var coordO:Coordenada = barcos[seleccionado].calcularPosBarco(new Number(armaSeleccionada));
						ws.ataqueBarco(idPartida, jugadores[bando], seleccionado, armaSeleccionada, coordO.getX(), coordO.getY(), xTo, yTo);
					}
				break;
			}
		}
	}
	_event.preventDefault();
	_event.stopPropagation();
	cnvMain.setFocus();
}

private function cambiarCursor(_accion:String):void {
	if( accion != ACC_MOVER ) _accion = accion;
	switch (_accion) {
		case ACC_MOVER:
			CursorManager.removeAllCursors();
			CursorManager.setCursor(cursorMovimiento);
		break;
		case ACC_DISPARAR:
			CursorManager.removeAllCursors();
			CursorManager.setCursor(cursorAtaque);
		break;
		case ACC_VIRAR:
			CursorManager.removeAllCursors();
			CursorManager.setCursor(cursorVirar);
		break;
		default:
			CursorManager.removeAllCursors();
			CursorManager.removeBusyCursor();
		break;
	}
}

/**
 * 
 * @param _accion
 * 
 */
private function cambiarAccion(_accion:String, _event: MouseEvent=null): void {
	if ( _event != null ) _event.stopPropagation();
	accion = _accion;
	if ( barcos && barcos[seleccionado] ) barcos[seleccionado].eliminarAreaDisparo();
	cnvBotonesSecundarios.visible = false;
	switch (accion) {
		case ACC_DISPARAR:
			if(!(barcos[seleccionado] as Barco).getEnDoceMillas().length){
				cnvBotonesSecundarios.visible = true;
			} else {
				accion = ACC_MOVER;
			}
		break;
		default:
			var keys:Array = accion.split("_");
			if ( keys[0] == PREFIJO_ARMA ) {
				if(!(barcos[seleccionado] as Barco).getEnDoceMillas().length){
					if ( keys[1] == TIPO_TORPEDO ){
						//para el torpedo dispara directamente
						var coordO:Coordenada = barcos[seleccionado].calcularPosBarco(3);
						var coordD:Coordenada = barcos[seleccionado].calcularPosBarco(4);//es el frente del barco
						ws.ataqueBarco(idPartida, jugadores[bando], seleccionado, keys[1], coordO.getX(), coordO.getY(), coordD.getX(), coordD.getY());
						accion = ACC_MOVER;//dejo en mover para que se de cuenta que ya disparo
					} else {
						accion = ACC_DISPARAR;
						armaSeleccionada = keys[1];
						barcos[seleccionado].agregarAreaDisparo(keys[1]);
					}
				} else {
					accion = ACC_MOVER;
				}
			}
		break;
	}
	cambiarCursor(accion);
}

/**
 * Cambia de barco activo
 * 
 */
private function cambiarBarco(_event: MouseEvent = null): void {
	if( _event != null ) _event.stopPropagation();
	barcos[seleccionado].eliminarAreaVisibilidad();
	if ( ultimoSeleccionado.length == 0 ) ultimoSeleccionado = getBarcosPorColor(bando);
	if ( ultimoSeleccionado.length > 0 ) {
		var barco:Barco = ultimoSeleccionado.shift(); 
		seleccionado = barco.getId();
		actualizarInfoBarcoSeleccionado();
	}
	barcos[seleccionado].agregarAreaVisibilidad(cambiarCursor);
	desplazarPantallaTo(barcos[seleccionado].getXPos(), barcos[seleccionado].getYPos() );
}

private function clickBarco(_event:MouseEvent):void {
	if ( _event.currentTarget.parent.hasOwnProperty("name") && _event.currentTarget.parent.name == bando ) {
		_event.stopPropagation();
		barcos[seleccionado].eliminarAreaVisibilidad();
		seleccionado = _event.currentTarget.parent.id;
		barcos[seleccionado].agregarAreaVisibilidad(cambiarCursor);
		actualizarInfoBarcoSeleccionado();		
	}
}

private function controlVisibilidad(_event:Event):void {
	_event.stopPropagation();
	if ( _event.target.parent.hasOwnProperty("id") && (barcos[_event.target.parent.id] is Barco) && barcos[_event.target.parent.id].getAreaVisibilidad()) {
		var thisBarco : Barco = barcos[_event.target.parent.id];
		var thisArea : DisplayObject = thisBarco.getAreaVisibilidad();
		//Antes de chocar con el barco se fija si lo ve je
		for (var i:String in barcos) {
			if ( thisBarco.getId() != i ) {
				if ( barcos[i] is Barco ) {
					var barco: Barco = barcos[i];
					if ( !barco.isVisible() ) {
						if ( hitTest(thisArea, barco.getObject()) ) {
							barco.setVisible(true);
						}
					}
				}
			}
		}
		//Test colision con el puerto
		for (var r:String in puertos) {
			var puert:Puerto = puertos[r];
			if ( !puert.isVisible() ) {
				if ( hitTest(thisArea, puert.getObject()) ) {
					puert.setVisible(true);
				}
			}
		}
	}
}

private function controlContactoBarco(_event:Event):void {
	_event.stopPropagation();
	if ( _event.target.parent.hasOwnProperty("id") && (barcos[_event.target.parent.id] is Barco)) {
		var thisBarco : Barco = barcos[_event.target.parent.id];
		var thisBarcoObject : DisplayObject = thisBarco.getObject();
		var thisArea : DisplayObject = thisBarco.getAreaVisibilidad();
		var rect:Rectangle;
		var h:Number;
		var popa:Coordenada;
		var destino: Coordenada;
		
		//Test colision con los barcos
		for (var i:String in barcos) {
			if ( thisBarco.getId() != i ) {
				if ( barcos[i] is Barco ) {
					var barco: Barco = barcos[i];
					if ( !thisBarco.isStopped() && hitTest(thisBarcoObject, barco.getObject()) ) {
						thisBarco.setStopped(true);
						rect = hitTestRectangle(thisBarcoObject, barco.getObject());
						thisBarco.detener();
						if ( thisBarco.getNombreBando() == bando ) {
							popa = thisBarco.calcularPosBarco(1);
							h = Math.sqrt(Math.pow(popa.getX() - (rect.x + pantalla.getXPantalla()), 2) + Math.pow(popa.getY() - (rect.y + pantalla.getYPantalla()), 2));
							if ( h < thisBarco.getAncho()/2 ) {
								h = -1;
							} else {
								h = 1
							}
							destino = thisBarco.calcularRetroceso( 10 * h, 10 * h );
							ws.movimientoBarco(
								idPartida, jugadores[bando], thisBarco.getId(), destino.getX(), destino.getY(),
								thisBarco.getAngulo()
							);
						}
						break;
					}
				}
			}
		}
		
		//Test colision con el puerto
		for (var r:String in puertos) {
			var puert:Puerto = puertos[r];
			if ( !thisBarco.isStopped() && hitTest(thisBarcoObject, puert.getObject()) ) {
				thisBarco.setStopped(true);
				rect = hitTestRectangle(thisBarcoObject, puert.getObject());
				thisBarco.detener();
				if ( thisBarco.getNombreBando() == bando ) {
					popa = thisBarco.calcularPosBarco(1);
					h = Math.sqrt(Math.pow(popa.getX() - (rect.x + pantalla.getXPantalla()), 2) + Math.pow(popa.getY() - (rect.y + pantalla.getYPantalla()), 2));
					if ( h < thisBarco.getAncho()/2 ) {
						h = -1;
					} else {
						h = 1
					}
					destino = thisBarco.calcularRetroceso( 10 * h, 10 * h );
					ws.movimientoBarco(
						idPartida, jugadores[bando], thisBarco.getId(), destino.getX(), destino.getY(),
						thisBarco.getAngulo()
					);
					if (puertosHabilitados){
						if (puert.getOcupado()) {
							Alert.show(textos['puertoOcupado'], textos['aviso'], Alert.OK , this);
							//trace("Hit puerto ocupado. No entra");
						} else {
							Alert.show(textos['entrarPuerto'], textos['aviso'], Alert.YES | Alert.NO , this,
							function(event:CloseEvent):void {
								//trace("Respuesta de puerto");
								if (event.detail == Alert.YES) {
									thisBarco.setEnPuerto(10, r);
									puert.setOcupado(true);
									thisBarco.posicionar(
										(puert.getXPos() + (puert.getAncho() / 2)),
										(puert.getYPos() + (puert.getAlto() /2) )
									);
									actualizarPosicionBarco(seleccionado);
									cambiarVistaLateral("reparacion", true);
									//trace("Limite de reparaciones: " + puert.getLimiteReparaciones());
									if (puert.getLimiteReparaciones() == 1) {
										mostrarOpcionesReparacion(r, seleccionado);
									} else {
										//trace("Enviamos reparacion de todo a la mitad. Barco: " + seleccionado);
										ws.repararEnPuerto(idPartida, r, seleccionado, "");
									}
									if ( r == "1" ) {
										ws.movimientoBarco(
											idPartida, jugadores[bando], thisBarco.getId(),
											(puert.getXPos() + (puert.getAncho()/2)),
											(puert.getYPos() + puert.getAlto() + thisBarco.getAncho()),
											thisBarco.getAngulo()
										);
									} else {
										ws.movimientoBarco(
											idPartida, jugadores[bando], thisBarco.getId(),
											(puert.getXPos() + puert.getAncho() + thisBarco.getAncho()),
											(puert.getYPos() + (puert.getAlto()/2)),
											thisBarco.getAngulo()
										);
									}
									thisBarco.setJump(true);
								} else {
									thisBarco.setStopped(false);
								}
							});
						}
					} else {
						Alert.show(textos['puertoInhabilitado'], textos['aviso'], Alert.OK , this);
					}
					break;
				}
			}
		}
		
		//Test colision con las doce millas
		for (s in doceMillas) {
			var millas:DoceMillas = doceMillas[s];
			if (hitTest(thisBarcoObject, millas.getObject())) { // Si toco con las doce millas
				if (thisBarco.getEnDoceMillas() != s) { // Si no estoy en las doce millas tengo que ver si puedo entrar
					var losBarcos: Array = getBarcosPorColor(BANDO_VERDE); 
					if (typeof losBarcos[0] != 'undefined') {
						if (losBarcos[0].getEnDoceMillas() != s) {
							thisBarco.setEnDoceMillas(s);
							if ( thisBarco.getNombreBando() == BANDO_VERDE ) {
								sacarBarcosDoceMillas(s);
							}
						} else {
							if (thisBarco.getNombreBando() != BANDO_VERDE) {
								thisBarco.setStopped(true);
								rect = hitTestRectangle(thisBarcoObject, millas.getObject());
								thisBarco.detener(); // Si no es el verde no se lo deja entrar
								if ( thisBarco.getNombreBando() == bando ) {
									popa = thisBarco.calcularPosBarco(1);
									h = Math.sqrt(Math.pow(popa.getX() - (rect.x + pantalla.getXPantalla()), 2) + Math.pow(popa.getY() - (rect.y + pantalla.getYPantalla()), 2));
									if ( h < thisBarco.getAncho()/2 ) {
										h = -1;
									} else {
										h = 1
									}
									destino = barcos[seleccionado].calcularRetroceso( 10 * h, 10 * h );
									ws.movimientoBarco(
										idPartida, jugadores[bando], thisBarco.getId(), destino.getX(), destino.getY(),
										thisBarco.getAngulo()
									);
								}
							}
							thisBarco.setEnDoceMillas("");
						}
					} else {
						thisBarco.setEnDoceMillas(s);
					}
				} else {
					thisBarco.setEnDoceMillas(s);
				}
				break;
			} else { // Si estoy en las doce millas, suertenpila barco verde
				thisBarco.setEnDoceMillas("");
			}
		}
		
		//Test colision con la tierra
		for (var s:String in tierra) {
			var tierr:Tierra = tierra[s];
			if ( !thisBarco.isStopped() && hitTest(thisBarcoObject, tierr.getObject()) ) {
				thisBarco.setStopped(true);
				rect = hitTestRectangle(thisBarcoObject, tierr.getObject());
				thisBarco.detener();
				if ( thisBarco.getNombreBando() == bando ) {
					popa = thisBarco.calcularPosBarco(1);
					h = Math.sqrt(Math.pow(popa.getX() - (rect.x + pantalla.getXPantalla()), 2) + Math.pow(popa.getY() - (rect.y + pantalla.getYPantalla()), 2));
					if ( h < thisBarco.getAncho()/2 ) {
						h = -1;
					} else {
						h = 1
					}
					destino = barcos[seleccionado].calcularRetroceso( 10 * h, 10 * h );
					ws.movimientoBarco(
						idPartida, jugadores[bando], thisBarco.getId(), destino.getX(), destino.getY(),
						thisBarco.getAngulo()
					);
				}
				break;
			}
		}
	}
}

private function controlContactoProyectil(_event:Event):void {
	_event.stopPropagation();
	if ( _event.target.parent.hasOwnProperty("id") && (proyectiles[_event.target.parent.id] is Proyectil)) {
		var thisPro : Proyectil = proyectiles[_event.target.parent.id];
		var thisProObject : DisplayObject = thisPro.getObject();
		var rect:Rectangle;
		for (var i:String in barcos) {
			if ( barcos[i] is Barco ) {
				var barco: Barco = barcos[i];
				if ( thisPro.getNombre() != barco.getId() && !barco.getEnDoceMillas().length) {//Con esto no basta
					//Hay que ver que pasa con los barcos aliados y el propio
					if ( hitTest(thisProObject, barco.getObject()) ) {
						//trace("Colision proyectil");
						if ( !barco.isVisible() ) barco.setVisible(true);
						thisPro.detener();
						if( barcos[thisPro.getIdBarco()].getNombreBando() == bando ) {
							if ( barco.getNombreBando() == BANDO_VERDE ) {
								puertosHabilitados = false;
							}
							ws.colisionArmaBarco(idPartida, thisPro.getIdBarco(), thisPro.getIdArma(), barco.getId());
						}
						break;
					}
				}
			}
		}
		//Test colision con las doce millas
		for (s in doceMillas) {
			var millas:DoceMillas = doceMillas[s];
			if (hitTest(thisProObject, millas.getObject())) {
				thisPro.detener("end");
				break;
			}
		}
		//Test colision con el puerto
		for (var r:String in puertos) {
			var puert:Puerto = puertos[r];
			if ( hitTest(thisProObject, puert.getObject()) ) {
				thisPro.detener("end");
				break;
			}	
		}
		//Test colision tierra
		for (var s:String in tierra) {
			var tierr:Tierra = tierra[s];
			if ( hitTest(thisProObject, tierr.getObject()) ) {
				thisPro.detener();
				break;
			}
		}
	}
}

private function sacarBarcosDoceMillas(_id:String): void {
	for (var i:String in barcos) {
		if ( barcos[i] is Barco ) {
			var barco: Barco = barcos[i];
			if ( barco.getEnDoceMillas() == _id && barco.getNombreBando() != BANDO_VERDE) {
				barco.setStopped(true);
				barco.setEnDoceMillas("");
				if ( barco.getNombreBando() == bando ) {
					if ( _id == "Norte" ) {
						ws.movimientoBarco(
							idPartida, jugadores[bando], barco.getId(), barco.getXPos(), barco.getYPos() + barco.getAncho() + ANCHO_DOCE_MILLAS,
							barco.getAngulo()
						);
					} else{
						ws.movimientoBarco(
							idPartida, jugadores[bando], barco.getId(), barco.getXPos() + barco.getAncho() + ANCHO_DOCE_MILLAS, barco.getYPos(),
							barco.getAngulo()
						);
					}
				}
				barco.setJump(true);
			}
		}
	}
}

private function anularDisparo(_nombreBarco:String, _idArma:String): void {
	ws.anularDisparo(idPartida, _nombreBarco, _idArma);
}

private function actualizarPosicionBarco(_idBarco:String): void {
	var barco:Barco = barcos[_idBarco];
	if ( barco.getNombreBando() == bando ) {
		ws.movimientoBarco(idPartida, jugadores[bando], barco.getId(), barco.getXPos(), barco.getYPos(), barco.getAngulo());
	}
}

private function eliminarBarco(_nombreBarco:String, _tipoFin:String): void {
	if ( _tipoFin == "Hundido" ) {
		barcos[_nombreBarco].cambiarImagen("img/barcoHundido-"+barcos[_nombreBarco].getTipoBarco()+".swf");
		if (barcos[_nombreBarco].getNombreBando() == bando) cambiarVistaLateral("hundido", true);
	}
}

private function eliminarBarcos(): void {
	for (var i:String in barcos) {
		if ( barcos[i] is Barco ) {
			var barc:Barco = barcos[i];
			if ( barc.paraBorrar() != 0) {
				barc.setBorrar(barc.paraBorrar() - 1);
				if ( barc.paraBorrar() == 0) {
					barc.eliminar();
					if ( barc.getNombreBando() == bando ) cambiarVistaLateral("mover", false);
					barcos[i] = null;			
				}
			}
		}
	}
}

private function eliminarProyectil(_nombreBarco:String, _codigoArma:String, _idPro:String, _tipoFin:String): void {
	if ( _tipoFin == "stop" ) {
		proyectiles[_nombreBarco + "_" + _codigoArma + "_" + _idPro].cambiarImagen(explosion);
	} else {
		proyectiles[_nombreBarco + "_" + _codigoArma + "_" + _idPro].cambiarImagen(explosionAgua);
	}
	proyectiles[_nombreBarco + "_" + _codigoArma + "_" + _idPro].setBorrar(3);
}

private function eliminarProyectiles(): void {
	for (var i:String in proyectiles) {
		if ( proyectiles[i] is Proyectil ) {
			var proy:Proyectil = proyectiles[i];
			if ( proy.paraBorrar() != 0 ) {
				proy.setBorrar(proy.paraBorrar() - 1);
				if ( proy.paraBorrar() == 0 ) {
					proy.eliminar();
					proyectiles[i] = null;			
				}
			}
		}
	}
}

private function getBarcosPorColor(_color: String): Array {
	var retorno: Array = [];
	for (var b:String in barcos) {
		if (barcos[b] is Barco && barcos[b].getNombreBando() == _color) {
			retorno.push(barcos[b]);
		}
	}
	return retorno;
}

private function cambiarVistaLateral(_accion: String, _play: Boolean = true ): void {
	var laterals:Array = cnvVistaLateral.getChildren();
	var swfLateral : MovieClipSWFLoader;
	for ( var i:String in laterals){
		if ( _accion + "SWFLateral" == laterals[i].id ) {
			swfLateral = laterals[i];
		} else {
			laterals[i].stop();
			laterals[i].visible=false;
		}
	}
	swfLateral.visible = true;
	if ( _play ) {
		swfLateral.play();
	} else {
		swfLateral.stop();
	}
}

private function cambiarImagenBarco( _event:EffectEvent ): void {
	var idBarco:String = _event.target.target.id;
	var barco:Barco = barcos[idBarco]; 
	if ( _event.type == EffectEvent.EFFECT_START ) {
		//barco
		barco.cambiarImagen(barcosImg["mover-" + barco.getTipoBarco()]);
		cambiarVistaLateral("mover", true);
	} else {
		//barcoQuieto
		barco.cambiarImagen(barcosImg[barco.getTipoBarco()]);
		cambiarVistaLateral("mover", false);
	}
}

private function cambiarLateralProyectil( _event:EffectEvent ): void {
	var idProyectil:String = _event.target.target.id;
	var proyectil:Proyectil = proyectiles[idProyectil];
	if ( _event.type == EffectEvent.EFFECT_START ) {
		if ( proyectil is Torpedo ){
			cambiarVistaLateral("torpedo", true);
		} else {
			cambiarVistaLateral("artilleria", true);
		}
	} else {
		cambiarVistaLateral("mover", false);
	}
}

public function hitTest(_object1:DisplayObject, _object2:DisplayObject):Boolean {
	return HitTest.complexHitTestObject(_object1, _object2);
}

public function hitTestRectangle(_object1:DisplayObject, _object2:DisplayObject): Rectangle {
	return HitTest.complexIntersectionRectangle(_object1, _object2);
}

public function estaEnPuerto(_x: Number, _y: Number) : Boolean {
	var ret: Boolean = false;
	for (var a:String in puertos) {
		if (puertos[a].getXPos() < _x && puertos[a].getXPos() + puertos[a].getAncho() > _x &&
			puertos[a].getYPos() < _y && puertos[a].getYPos() + puertos[a].getAlto() > _y) {
				ret = true;
				break;
			}
	}
	return ret;
}